package com.pi.shisan.util;

import com.pi.shisan.util.spipoint.SpiPoint;

import java.util.Random;

public class DefaultFont8x8 {

    /**
     * 笑脸娃娃
     */
    public static final long FACE_HAPPY = 4342214966986228284L;
    public static final long FACE_UNHAPPY = 4342214966785688124L;
    public static final long FACE_NORMAL = 4342214966382248508L;
    public static final long FACE_SHRPRISE = 4342214966784901692L;

    /**
     * 符号
     */
    public static final long SIGN_FALSE = -9132697443079273855L;
    public static final long SIGN_TRUE = 283966729879552L;
    public static final long SIGN_WARN = 1739555223478305279L;
    public static final long SIGN_LOADING = 9097873883144667774L;
    public static final long SIGN_LOADING_FILL = 9114788770027961982L;
    public static final long SIGN_EMBARRASS = -35565062528073217L;
    public static final long SIGN_LOVE = 7393082656524739608L;
    public static final long SIGN_LOVE_FILL = 7421932185898073112L;
    //?
    public static final long SIGN_UNKONW = 2027184998608011272L;
    //#
    public static final long SIGN_PAND = 10271792857752576L;
    //:
    public static final long SIGN_COLON = 140737496743936L;


    /**
     * 数字
     */
    public static final long NUM_ZERO = 2027224744808555036L;
    public static final long NUM_ONE = 583224982331983900L;
    public static final long NUM_TWO = 2027184998608544318L;
    public static final long NUM_THREE = 2027185032866701852L;
    public static final long NUM_FOUR = 291630221331661828L;
    public static final long NUM_FIVE = 9097342148642226748L;
    public static final long NUM_SIX = 4342103893170340412L;
    public static final long NUM_SEVEN = 9079822015070736400L;
    public static final long NUM_EIGHT = 4342105817315689020L;
    public static final long NUM_NINE = 4342105824827671100L;

    /**
     * 双位数字显示
     */
    public static final long NUM_0_LEFT = -2260630400126681088L;
    public static final long NUM_0_RIGHT = 145528082076599554L;
    public static final long NUM_1_LEFT= 4665799861336014848L;
    public static final long NUM_1_RIGHT = 145806245582995975L;
    public static final long NUM_2_LEFT = -4602607896914558976L;
    public static final long NUM_2_RIGHT = 145523666799822087L;
    public static final long NUM_3_LEFT = -4602467572279934976L;
    public static final long NUM_3_RIGHT = 145523671077815554L;
    public static final long NUM_4_LEFT = -6872246602786930688L;
    public static final long NUM_4_RIGHT = 145815076170826242L;
    public static final long NUM_5_LEFT = -2269602965302018048L;
    public static final long NUM_5_RIGHT = 505533482005496070L;
    public static final long NUM_6_LEFT = -2269567230637244416L;
    public static final long NUM_6_RIGHT = 145526986859939074L;
    public static final long NUM_7_LEFT = -2296800487611039744L;
    public static final long NUM_7_RIGHT = 504685741377586180L;
    public static final long NUM_8_LEFT = -2260560031382503424L;
    public static final long NUM_8_RIGHT = 145528069191697666L;
    public static final long NUM_9_LEFT = -2260560581138317312L;
    public static final long NUM_9_RIGHT = 145528073419293954L;
    public static final long SIGN_SMALL_COLON = 36029346774777856L;


    /**
     * 大写字母
     */
    public static final long UPPER_A = 2328511608365514752L;
    public static final long UPPER_B = -1114376436841447424L;
    public static final long UPPER_C = 8108872452563533824L;
    public static final long UPPER_D = -1114490786050736128L;
    public static final long UPPER_E = -540167518577229824L;
    public static final long UPPER_F = -540167520590495744L;
    public static final long UPPER_G = 8106682225401004032L;
    public static final long UPPER_H = -8608357422437761024L;
    public static final long UPPER_I = 8079493055192760320L;
    public static final long UPPER_J = -1143878432174637056L;
    public static final long UPPER_K = -8025202740131004416L;
    public static final long UPPER_L = -9187201948565110784L;
    public static final long UPPER_M = -8585927247255306240L;
    public static final long UPPER_N = -8590430916139024384L;
    public static final long UPPER_O = 8108881248656556032L;
    public static final long UPPER_P = -1114376473080233984L;
    public static final long UPPER_Q = 8108881282882076672L;
    public static final long UPPER_R = -1114376404226539520L;
    public static final long UPPER_S = 8106602510807990272L;
    public static final long UPPER_T = -567418230700769280L;
    public static final long UPPER_U = -8608480568142725120L;
    public static final long UPPER_V = -8608542382654226432L;
    public static final long UPPER_W = -6293595038400118784L;
    public static final long UPPER_X = -8624357756163325952L;
    public static final long UPPER_Y = -8624357964066586624L;
    public static final long UPPER_Z = -571921689265307648L;

    /**
     * 动态组合
     */
    public static final long[] GIF_CIRCLE_LOADING = new long[]{
            9123619555872702846L,
            9119115964835266942L,
            9116864165055136126L,
            9115738265148424574L,
            9115736066125170046L,
            9115736057535237502L,
            9115736057501687166L,
            9115736057501564286L,
            9115736057505757566L,
            9115736058579497342L,
            9115736333457400190L,
            9115806702201569662L,
            9124813901452116350L,
            9129317500005745022L,
            9131569024941523326L,
            9132624556104188286L,
    };
    public static final long[] GIF_LINE_LOADING = new long[]{
            35608723204439552L,
            35608481746746880L,
            35608361017900544L,
            35608300653477376L,
            35608542111170048L,
            35608662840016384L
    };

    /**
     * 获取SPI点
     * @param points
     * @return
     */
    public static byte[] getPoints(long points){
        byte ps[] = new byte[8];
        for (int i = 0; i < ps.length; i++) {
            ps[i] = (byte)(points >> (7 - i << 3) & 0xff);
        }
        return ps;
    }

    /**
     * 获取x,y坐标点
     * @param points
     * @return
     */
    public static int[] getPointsAsXy(long points) {
        byte[] bytePoints = getPoints(points);
        int[] allPoints = new int[64];
        int availableNum = 0;
        for (int y = 0; y < bytePoints.length; y++) {
            int p = bytePoints[y]&0xFF;
            for (int x = 0; x < 8; x++) {
                if ((p & 1 << 7 -x) != 0) {
                    allPoints[availableNum++] = x << 16 | y;
                }
            }
        }
        if (availableNum == 0) {
            return null;
        }
        if (availableNum == allPoints.length) {
            return allPoints;
        }
        int[] result = new int[availableNum];
        System.arraycopy(allPoints,0,result,0,availableNum);
        return result;
    }

    /**
     * 如果接线时如图这样接，则需要将点阵进行180度旋转
     * 注： DOUT<- [] <- DIN
     * <-[DIN]<-[DIN]<-[DIN]<-
     * ->[DIN]->[DIN]->[DIN]->    这一行的LED需要180度旋转，并交替位置
     * <-[DIN]<-[DIN]<-[DIN]<-
     * @param points
     * @return
     */
    public static long rotate180(long points) {
        long newPoints = 0, tmp, low, high, pl, ph;
        for (int i = 0; i < 8; i++) {
            if (i < 4) {
                newPoints = newPoints | (tmp = (points >> ((8 - i * 2 - 1) << 3) & (0xFFL << (i << 3))));
            } else {
                newPoints = newPoints | (tmp = (points << ((i - 1 - 3) * 2 + 1 << 3) & (0xFFL << (i << 3))));
            }
            if ((tmp = (tmp >> (i << 3) & 0xFF)) == 0L || tmp == 0xFFL) {
                continue;
            }
            for (int j = 0; j < 4; j++) {
                //低位
                low = newPoints & (pl = 1L << j + (i << 3));
                //高位
                high = newPoints & (ph = (1L << (7 - j + (i << 3))));
                newPoints = low == 0L ? (newPoints & ~ph) : (newPoints | ph);
                newPoints = high == 0L ? (newPoints & ~pl) : (newPoints | pl);
            }
        }
        return newPoints;
    }
//
    /**
     * 获取所有坐标点
     * @param points
     * @return
     */
    public static long[] getAllSingleOfPoints(long points){
        byte num = getNumOfPoints(points);
        long singleOfPoints[] = new long[num];
        long p;
        for (int i = 0,j =0; i < 64 && j<num; i++) {
            if(((p = 1L << i & points)) != 0){
                singleOfPoints[j] = p;
                j ++;
            }
        }
        return singleOfPoints;
    }

    public static long[] randomSinglePoints(long[] points){
        int r = 0;
        Random random = new Random();
        long newPoints[] = new long[points.length];
        System.arraycopy(points,0,newPoints,0,points.length);
        for (int i = 0; i < newPoints.length; i++) {
            r = random.nextInt(newPoints.length);
            if(newPoints[i] != newPoints[r]){
                newPoints[i] = newPoints[i] ^ newPoints[r];
                newPoints[r] = newPoints[i] ^ newPoints[r];
                newPoints[i] = newPoints[i] ^ newPoints[r];
            }
        }
        return newPoints;
    }

    /**
     * 获取点个数
     * @param points
     * @return
     */
    private static byte getNumOfPoints(long points){
        byte res = 0;
        while(points != 0){
            points = points & (points - 1);
            res ++;
        }
        return res;
    }

//    public static void main(String[] args) throws Exception {
//        long[] all = getAllSingleOfPoints(SIGN_FALSE);
//        long o = 0L;
//        for (int i = 0; i < all.length; i++) {
//            byte []v = getPoints(o |= all[i]);
//            PointToSPI p = new PointToSPI();
//            Field f = ReflectUtil.getFieldByName("result",p.getClass());
//            f.setAccessible(true);
//            f.set(p,v);
//            f.setAccessible(false);
//            System.out.println(p.toString());
//        }
//    }

    public static void main(String[] args) {

//        MergedSpi spi = new MergedSpi(4,3);
//        spi.add(0,0);
//        long[] pointsAll = spi.toSpiPoints();
//        SpiPoint spiPoint = new SpiPoint();
//        spiPoint.put(0,0);
//        spiPoint.put(1,1);
//        spiPoint.put(2,2);
//        System.out.println(spiPoint.toString());

//        byte[] points = getPoints(spiPoint.toSpiPoint());
//        for (int i = 0; i < points.length; i++) {
//            String str = Integer.toBinaryString(points[i]&0xFF);
//            for (int j = 0; j < 8 - str.length(); j++) {
//                System.out.print("0");
//            }
//            System.out.println(str);
//        }

//        int[] xy = getPointsAsXy(NUM_0_RIGHT);
//        if (xy == null) {
//            System.out.println("null");
//        } else {
//            SpiPoint spiPoint = new SpiPoint();
//            for (int v : xy) {
//                spiPoint.put((v >> 16 & 0xFFFF) - 5, v & 0xFFFF);
//            }
//            System.out.println(spiPoint.toString());
//            System.out.println(NUM_0_RIGHT);
//            System.out.println(spiPoint.toSpiPoint());
//        }

        SpiPoint spiPoint = new SpiPoint();
        spiPoint.put(0,2);
        spiPoint.put(0,5);
        System.out.println(spiPoint.toString());
        System.out.println(spiPoint.toSpiPoint());
    }
}
